using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlServerCe;
using System.Threading;

namespace FeedFly
{
    /// <summary>
    /// Form for listing feed items within a feed. 
    /// </summary>
    public partial class ItemListForm : Form
    {
        private int feedId;
        private int folderId;
        private string feedTitle;
        private const string MARK_READ = "Mark Read";
        private const string MARK_UNREAD = "Mark Unread";
        private const string READ_TEXT = "True";        

        // create delegate for updating UI from background thread
        private delegate void MarkAllItemsDelegate(bool isRead);
        private delegate void RefreshFeedDelegate(int feedId);

        public ItemListForm()
        {
            InitializeComponent();
        }

        private void ItemListForm_Load(object sender, EventArgs e)
        {
            this.itemListView.Focus();
        }

        #region Public Interface
        public void MarkAllItems(bool isRead)
        {
            if (InvokeRequired)
            {
                BeginInvoke((MarkAllItemsDelegate)MarkAllItems, new object[] { isRead });
                return;
            }

            int imgIndex = 0;

            if (isRead)
                this.markReadMenuItem.Text = MARK_UNREAD;
            else
            {
                imgIndex = 1;
                this.markReadMenuItem.Text = MARK_READ;
            }

            // loop through item list and change images
            for (int i = 0; i < itemListView.Items.Count; i++)
                itemListView.Items[i].ImageIndex = imgIndex;
        }     

        public void RefreshFeed(int feedId)
        {

            if (InvokeRequired)
            {
                BeginInvoke((RefreshFeedDelegate)RefreshFeed, new object[] { feedId });
                return;
            }

            if (feedId != this.feedId)
                return;

            // change cursor to WaitCursor
            Cursor.Current = Cursors.WaitCursor;

            // set feed title header
            this.feedTitleLabel.Text = this.feedTitle;

            // remove existing items
            if (this.itemListView.Items.Count > 0)
                this.itemListView.Items.Clear();

            this.itemListView.BeginUpdate();

            string[] columns = new string[4];

            SqlCeDataReader rdr = FeedItem.GetItemDataReader(feedId);

            bool isRead;

            while (rdr.Read())
            {
                columns[0] = rdr.GetString(2);
                columns[1] = rdr.GetInt32(0).ToString();
                columns[2] = rdr.GetDateTime(4).ToString("d");
                
                isRead = rdr.GetBoolean(6);

                columns[3] = isRead.ToString();

                ListViewItem item = new ListViewItem(columns);
                item.ImageIndex = (isRead) ? 0 : 1;

                this.itemListView.Items.Add(item);
            }

            rdr.Close();
            rdr.Dispose();

            this.itemListView.EndUpdate();

            if (itemListView.Items.Count > 0)
            {
                this.itemListView.Items[0].Focused = true;
                this.itemListView.Items[0].Selected = true;

                viewOriginalMenuItem.Enabled = true;
                previewMenuItem.Enabled = true;
                markReadMenuItem.Enabled = true;
            }
            else
            {
                viewOriginalMenuItem.Enabled = false;
                previewMenuItem.Enabled = false;
                markReadMenuItem.Enabled = false;
            }

            // change cursor back to default
            Cursor.Current = Cursors.Default;
        }

        public int GetCurrentFeedId()
        {
            return this.feedId;
        }

        public void LoadFeed(int feedId, int folderId, string feedTitle)
        {
            // clear existing items if feed changed
            if (feedId != this.feedId)
            {
                this.folderId = folderId;
                this.feedId = feedId;
                this.feedTitle = feedTitle;

                RefreshFeed(feedId);
            }
        }

        public void UpdateFeedTitle(FeedInterface feed)
        {
            if(this.feedId == feed.Id)            
                this.feedTitleLabel.Text = feed.Title;
        }

        #endregion

        private void viewOriginalMenuItem_Click(object sender, EventArgs e)
        {
            FeedItem item = FeedItem.GetItem(Convert.ToInt32(itemListView.FocusedItem.SubItems[1].Text));
            System.Diagnostics.Process.Start(item.Link, null);
        }

        private void viewItem()
        {
            Screens.Item.SetFeedItem(
                Convert.ToInt32(itemListView.FocusedItem.SubItems[1].Text)
                , folderId);

            Screens.Item.Show();
            markReadUI(true);
            Hide();          
        }

        private void previewMenuItem_Click(object sender, EventArgs e)
        {
            viewItem();
        }

        private void itemListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            // selected index changed event fires when items are cleared from listview, so test for empty list 
            if (this.itemListView.Items.Count > 0 && itemListView.SelectedIndices.Count > 0)
            {
                bool isRead = itemListView.Items[itemListView.SelectedIndices[0]].SubItems[3].Text == READ_TEXT;
                markReadMenuItem.Text = (isRead) ? MARK_UNREAD : MARK_READ;
            }
        }

        private void goBackMenuItem_Click(object sender, EventArgs e)
        {
            Screens.Main.Show();
            Hide();
        }

        private void markReadMenuItem_Click(object sender, EventArgs e)
        {
            bool isRead = itemListView.FocusedItem.SubItems[3].Text != READ_TEXT;
            
            // update read state in user interface
            markReadUI(isRead);

            ThreadPool.QueueUserWorkItem(new WaitCallback(markReadDB),
                new FeedItem.MarkRequest(
                    Convert.ToInt32(itemListView.FocusedItem.SubItems[1].Text)
                    , feedId
                    , folderId
                    , isRead));
        }

        private void markReadUI(bool isRead)
        {
            ListViewItem item = itemListView.FocusedItem;

            item.SubItems[3].Text = isRead.ToString();

            if (isRead)
            {
                markReadMenuItem.Text = MARK_UNREAD;
                item.ImageIndex = 0;
            }
            else
            {
                markReadMenuItem.Text = MARK_READ;
                item.ImageIndex = 1;
            }
        }

        private void markReadDB(object mr)
        {
            // toggle read state in database
            FeedItem.Mark((FeedItem.MarkRequest)mr);
        }

        private void itemListView_KeyDown(object sender, KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                //case Keys.Enter:
                case Keys.Right:
                    if(this.itemListView.FocusedItem != null) viewItem();
                    break;
                case Keys.Left:
                    goBack();
                    break;
            }
        }

        private void goBack()
        {
            Screens.Main.Show();
            Hide();
        }
        /// <summary>
        /// ItemActivate event handler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <remarks>
        /// This event fires when touching an item or hitting the action key (middle key in dpad)
        /// </remarks>
        private void itemListView_ItemActivate(object sender, EventArgs e)
        {
            viewItem();
        }

        private void goBackPictureBox_Click(object sender, EventArgs e)
        {
            goBack();
        }

        private void goBackPictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            toggleGoBackButton(true);
        }

        private void goBackPictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            toggleGoBackButton(false);
        }

        private void toggleGoBackButton(bool selected)
        {
            goBackPictureBox.Visible = !selected;
            goBackPictureBoxSelected.Visible = selected;
        }

        private void downloadUpdateMenuItem_Click(object sender, EventArgs e)
        {
            Net.EnqueueDownload(Feed.GetFeed(this.feedId));
            ThreadPool.QueueUserWorkItem(new WaitCallback(Net.ProcessDownloads));
        }

        private void refreshMenuItem_Click(object sender, EventArgs e)
        {
            this.RefreshFeed(this.feedId);
        }

        private void markFeed(object mr)
        {
            Feed.MarkRequest r = (Feed.MarkRequest)mr;
            Feed.Mark(r);
        }

        private void markAllMenuItem_Click(object sender, EventArgs e)
        {
            MarkAllItems(true);

            ThreadPool.QueueUserWorkItem(new WaitCallback(markFeed)
                , new Feed.MarkRequest(this.feedId, this.folderId, true));
        }

        private void editFeedMenuItem_Click(object sender, EventArgs e)
        {
            Screens.EditFeed.PrepareForm(this.feedId, Screens.Main.GetBreadCrumbs(), this);
            Screens.EditFeed.Show();
            Hide();
        }

    }
}